home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / share / pyshared / PIL / PdfImagePlugin.py < prev    next >
Text File  |  2006-12-03  |  5KB  |  211 lines

  1. #
  2. # The Python Imaging Library.
  3. # $Id: PdfImagePlugin.py 2438 2005-05-25 21:09:48Z Fredrik $
  4. #
  5. # PDF (Acrobat) file handling
  6. #
  7. # History:
  8. # 1996-07-16 fl   Created
  9. # 1997-01-18 fl   Fixed header
  10. # 2004-02-21 fl   Fixes for 1/L/CMYK images, etc.
  11. # 2004-02-24 fl   Fixes for 1 and P images.
  12. #
  13. # Copyright (c) 1997-2004 by Secret Labs AB.  All rights reserved.
  14. # Copyright (c) 1996-1997 by Fredrik Lundh.
  15. #
  16. # See the README file for information on usage and redistribution.
  17. #
  18.  
  19. ##
  20. # Image plugin for PDF images (output only).
  21. ##
  22.  
  23. __version__ = "0.4"
  24.  
  25. import Image, ImageFile
  26. import StringIO
  27.  
  28.  
  29. #
  30. # --------------------------------------------------------------------
  31.  
  32. # object ids:
  33. #  1. catalogue
  34. #  2. pages
  35. #  3. image
  36. #  4. page
  37. #  5. page contents
  38.  
  39. def _obj(fp, obj, **dict):
  40.     fp.write("%d 0 obj\n" % obj)
  41.     if dict:
  42.         fp.write("<<\n")
  43.         for k, v in dict.items():
  44.             if v is not None:
  45.                 fp.write("/%s %s\n" % (k, v))
  46.         fp.write(">>\n")
  47.  
  48. def _endobj(fp):
  49.     fp.write("endobj\n")
  50.  
  51. ##
  52. # (Internal) Image save plugin for the PDF format.
  53.  
  54. def _save(im, fp, filename):
  55.  
  56.     #
  57.     # make sure image data is available
  58.     im.load()
  59.  
  60.     xref = [0]*(5+1) # placeholders
  61.  
  62.     fp.write("%PDF-1.2\n")
  63.     fp.write("% created by PIL PDF driver " + __version__ + "\n")
  64.  
  65.     #
  66.     # Get image characteristics
  67.  
  68.     width, height = im.size
  69.  
  70.     # FIXME: Should replace ASCIIHexDecode with RunLengthDecode (packbits)
  71.     # or LZWDecode (tiff/lzw compression).  Note that PDF 1.2 also supports
  72.     # Flatedecode (zip compression).
  73.  
  74.     bits = 8
  75.     params = None
  76.  
  77.     if im.mode == "1":
  78.         filter = "/ASCIIHexDecode"
  79.         colorspace = "/DeviceGray"
  80.         procset = "/ImageB" # grayscale
  81.         bits = 1
  82.     elif im.mode == "L":
  83.         filter = "/DCTDecode"
  84.         # params = "<< /Predictor 15 /Columns %d >>" % (width-2)
  85.         colorspace = "/DeviceGray"
  86.         procset = "/ImageB" # grayscale
  87.     elif im.mode == "P":
  88.         filter = "/ASCIIHexDecode"
  89.         colorspace = "[ /Indexed /DeviceRGB 255 <"
  90.         palette = im.im.getpalette("RGB")
  91.         for i in range(256):
  92.             r = ord(palette[i*3])
  93.             g = ord(palette[i*3+1])
  94.             b = ord(palette[i*3+2])
  95.             colorspace = colorspace + "%02x%02x%02x " % (r, g, b)
  96.         colorspace = colorspace + "> ]"
  97.         procset = "/ImageI" # indexed color
  98.     elif im.mode == "RGB":
  99.         filter = "/DCTDecode"
  100.         colorspace = "/DeviceRGB"
  101.         procset = "/ImageC" # color images
  102.     elif im.mode == "CMYK":
  103.         filter = "/DCTDecode"
  104.         colorspace = "/DeviceCMYK"
  105.         procset = "/ImageC" # color images
  106.     else:
  107.         raise ValueError("cannot save mode %s" % im.mode)
  108.  
  109.     #
  110.     # catalogue
  111.  
  112.     xref[1] = fp.tell()
  113.     _obj(fp, 1, Type = "/Catalog",
  114.                 Pages = "2 0 R")
  115.     _endobj(fp)
  116.  
  117.     #
  118.     # pages
  119.  
  120.     xref[2] = fp.tell()
  121.     _obj(fp, 2, Type = "/Pages",
  122.                 Count = 1,
  123.                 Kids = "[4 0 R]")
  124.     _endobj(fp)
  125.  
  126.     #
  127.     # image
  128.  
  129.     op = StringIO.StringIO()
  130.  
  131.     if filter == "/ASCIIHexDecode":
  132.         if bits == 1:
  133.             # FIXME: the hex encoder doesn't support packed 1-bit
  134.             # images; do things the hard way...
  135.             data = im.tostring("raw", "1")
  136.             im = Image.new("L", (len(data), 1), None)
  137.             im.putdata(data)
  138.         ImageFile._save(im, op, [("hex", (0,0)+im.size, 0, im.mode)])
  139.     elif filter == "/DCTDecode":
  140.         ImageFile._save(im, op, [("jpeg", (0,0)+im.size, 0, im.mode)])
  141.     elif filter == "/FlateDecode":
  142.         ImageFile._save(im, op, [("zip", (0,0)+im.size, 0, im.mode)])
  143.     elif filter == "/RunLengthDecode":
  144.         ImageFile._save(im, op, [("packbits", (0,0)+im.size, 0, im.mode)])
  145.     else:
  146.         raise ValueError("unsupported PDF filter (%s)" % filter)
  147.  
  148.     xref[3] = fp.tell()
  149.     _obj(fp, 3, Type = "/XObject",
  150.                 Subtype = "/Image",
  151.                 Width = width,
  152.                 Height = height,
  153.                 Length = len(op.getvalue()),
  154.                 Filter = filter,
  155.                 BitsPerComponent = bits,
  156.                 DecodeParams = params,
  157.                 ColorSpace = colorspace)
  158.  
  159.     fp.write("stream\n")
  160.     fp.write(op.getvalue())
  161.     fp.write("\nendstream\n")
  162.  
  163.     _endobj(fp)
  164.  
  165.     #
  166.     # page
  167.  
  168.     xref[4] = fp.tell()
  169.     _obj(fp, 4)
  170.     fp.write("<<\n/Type /Page\n/Parent 2 0 R\n"\
  171.              "/Resources <<\n/ProcSet [ /PDF %s ]\n"\
  172.              "/XObject << /image 3 0 R >>\n>>\n"\
  173.              "/MediaBox [ 0 0 %d %d ]\n/Contents 5 0 R\n>>\n" %\
  174.              (procset, width, height))
  175.     _endobj(fp)
  176.  
  177.     #
  178.     # page contents
  179.  
  180.     op = StringIO.StringIO()
  181.  
  182.     op.write("q %d 0 0 %d 0 0 cm /image Do Q\n" % (width, height))
  183.  
  184.     xref[5] = fp.tell()
  185.     _obj(fp, 5, Length = len(op.getvalue()))
  186.  
  187.     fp.write("stream\n")
  188.     fp.write(op.getvalue())
  189.     fp.write("\nendstream\n")
  190.  
  191.     _endobj(fp)
  192.  
  193.     #
  194.     # trailer
  195.     startxref = fp.tell()
  196.     fp.write("xref\n0 %d\n0000000000 65535 f \n" % len(xref))
  197.     for x in xref[1:]:
  198.         fp.write("%010d 00000 n \n" % x)
  199.     fp.write("trailer\n<<\n/Size %d\n/Root 1 0 R\n>>\n" % len(xref))
  200.     fp.write("startxref\n%d\n%%%%EOF\n" % startxref)
  201.     fp.flush()
  202.  
  203. #
  204. # --------------------------------------------------------------------
  205.  
  206. Image.register_save("PDF", _save)
  207.  
  208. Image.register_extension("PDF", ".pdf")
  209.  
  210. Image.register_mime("PDF", "application/pdf")
  211.